//package miniparser;
//import minijava.*;
//import java.util.*;
//import System.IO.*;

public class MiniJVMGenerator : MinijavaVisitor, Constants {
    TextWriter writer;
    public MiniJVMGenerator(String filename) {
        try {
            writer = new StreamWriter(filename + ".jvm");
        }
        catch (IOException ioe) {
            Console.WriteLine(ioe);
        }
    }
    public void flush() {
        writer.Flush();
        writer.Close();
    }
    int declcounter = 0;
    int loopcounter = 0;
    int ifcounter = 0;
    Dictionary<String, int?> symtab = new Dictionary<String, int?>();
    public void postVisit(Program p) {
        writer.WriteLine("HALT");
    }
    public bool preVisit(Stmt.Assign i) {
        writer.Write("// " + i);
        return true;
    }
    public void postVisit(Stmt.Assign i) {
        writer.WriteLine("STORE " + symtab[i.lhs]);
    }
    public bool preVisit(Stmt.Write i) {
        writer.Write("// " + i);
        return true;
    }
    public void postVisit(Stmt.Write i) {
        writer.WriteLine("WRITE");
    }
    public void visit(Stmt.Read i) {
        writer.Write("// " + i);
        writer.WriteLine("READ");
        writer.WriteLine("STORE " + symtab[i.lhs]);
    }
    public bool preVisit(Stmt.IfThenElse i) {
        int e = ifcounter++;
        int end = ifcounter++;
        writer.WriteLine("// " + i.cond);
        i.cond.accept(this);
        writer.WriteLine("FJUMP IF" + e);
        i.then.accept(this);
        if (i.els != null)
            writer.WriteLine("JUMP IF" + end);
        writer.Write("IF" + e + ":");
        if (i.els != null) {
            i.els.accept(this);
            writer.WriteLine("IF" + end + ":");
        }
        return false;
    }
    public bool preVisit(Stmt.Loop i) {
        int loop = loopcounter++;
        int loopexit = loopcounter++;
        writer.WriteLine("//" + i.cond + " ??");
        writer.Write("L" + loop + ":");
        i.cond.accept(this);
        writer.WriteLine("FJUMP L" + loopexit);
        i.body.accept(this);
        writer.WriteLine("JUMP L" + loop);
        writer.Write("L" + loopexit + ":");
        return false;
    }
    public bool preVisit(Decl d) {
        writer.Write("//" + d);
        return true;
    }
    public void postVisit(Decl d) {
        foreach (Expr.Identifier s in d.varlist) symtab.Add(s.i, declcounter++);
        writer.WriteLine("ALLOC " + d.varlist.Count);
    }
    public void postVisit(Cond.BUnOp i) {
        writer.WriteLine("NOT");
    }
    public void postVisit(Cond.BinCond i) {
        if (i.op == LEQ) writer.WriteLine("LEQ");
        if (i.op == LE) writer.WriteLine("LESS");
        if (i.op == GTQ) writer.WriteLine("GTQ");
        if (i.op == GT) writer.WriteLine("GT");
        if (i.op == EQ) writer.WriteLine("EQ");
        if (i.op == NEQ) writer.WriteLine("NEQ");
    }
    public void postVisit(Cond.BBinCond i) {
        if (i.op == AND) writer.WriteLine("AND");
        if (i.op == OR) writer.WriteLine("OR");
    }
    public void visit(Cond.BoolConst d) {
        writer.WriteLine("???");
    }
    public void visit(Expr.Identifier d) {
        writer.WriteLine("LOAD " + symtab[d.i]);
    }
    public void visit(Expr.IntConst d) {
        writer.WriteLine("CONST " + d.i);
    }
    public void postVisit(Expr.Binex i) {
        if (i.op == PLUS) writer.WriteLine("ADD");
        if (i.op == MINUS) writer.WriteLine("SUB");
        if (i.op == MULT) writer.WriteLine("MUL");
        if (i.op == DIV) writer.WriteLine("DIV");
        if (i.op == MOD) writer.WriteLine("MOD");
    }
    public void postVisit(Expr.Unex i) {
        writer.WriteLine("NEG");
    }
}
